//-------------------------------------------------------------------
//	Copyright (c) 2012-2014 Zhirnov Andrey
//	This file is part of the "UXGEN-ES" project.
//	See copyright notice in "Engine.h".
//-------------------------------------------------------------------

#pragma once

#include "Base/MetaData/MetaDataCommon.h"
#include "Graphics/MetaData/Meta.RenderState.h"
#include "Graphics/MetaData/Meta.GraphicsResources.h"

#ifdef ENGINE_META_DATA
#	include "UI/Types/ColorStyle.h"
#	include "UI/Types/UIAction.h"
#	include "UI/Types/UIMaterial.h"
#	include "UI/Types/UIFont.h"
#	include "UI/Types/UIImage.h"
#	include "UI/Resources/UILocaleResource.h"
#	include "UI/Systems/UserInterface.h"

	namespace MetaData
	{
		using namespace Engine;
		using namespace Base;
		using namespace UI;

	}	// MetaData
#endif



	//
	// Color Style
	//
#	define META_OBJECT			ColorStyleCfg
#	define META_OBJECT_NAME		TOSTRING( ColorStyle )
#	define META_NAME			MetaColorStyle
#	define META_BASECLASS		ColorStyle

#	define META_FIELDS( _decl ) \
		_decl( color4u,		idle,				Idle(),				color4u(0xFF) ) \
		_decl( color4u,		disabled,			Disabled(),			color4u(0xFF) ) \
		_decl( color4u,		checked,			Checked(),			color4u(0xFF) ) \
		_decl( color4u,		idle_pressed,		IdlePressed(),		color4u(0xFF) ) \
		_decl( color4u,		checked_pressed,	CheckedPressed(),	color4u(0xFF) )
			
#	include "Base/MetaData/MetaDataObject.h"
	


	//
	// UI Action
	//
	
#	ifdef ENGINE_META_DATA
	namespace MetaData
	{
		template <>
		inline void MetaDataUtils::Copy<> (UIAction &left, string &right, const EngineSubSystemsRef ess)
		{
			if ( not right.Empty() ) {
				CHECK_ERR( ess->GetUserInterface()->GetActionManager()->GetAction( right, left ), void() );
			}
		}

	}	// MetaData
#	endif


	
	//
	// UI Material
	//
#	define META_OBJECT			UIMaterialCfg
#	define META_OBJECT_NAME		TOSTRING( UIMaterial )
#	define META_NAME			MetaUIMaterial

#	define META_FIELDS( _decl ) \
		_decl( ColorStateSeparateCfg,	colorState,			,	) \
		_decl( string,					program,			,	) \
		_decl( bool,					colorStateDefined,	,	false )
			
#	include "Base/MetaData/MetaDataObject.h"
	

#	ifdef ENGINE_META_DATA
	namespace MetaData
	{
		template <>
		inline void MetaDataUtils::Copy<> (UIMaterial &left, UIMaterialCfg &right, const EngineSubSystemsRef ess)
		{
			ProgramPtr	prog;
			MetaDataUtils::Copy( prog, right.program, ess );
			left.SetProgram( prog );

			if ( right.colorStateDefined )
			{
				RenderState::ColorStateSeparate	cs;
				MetaDataUtils::Copy( cs, right.colorState, ess );
				left.SetColorState( cs );
			}
		}

	}	// MetaData
#	endif



	//
	// UI Font
	//
#	define META_OBJECT			UIFontCfg
#	define META_OBJECT_NAME		TOSTRING( UIFont )
#	define META_NAME			MetaUIFont

#	define META_FIELDS( _decl ) \
		_decl( string,			program,				,	) \
		_decl( string,			font,					,	) \
		_decl( ColorStyleCfg,	colors,					,	) \
		_decl( int,				text_direction,			,	0 ) \
		_decl( float,			spacing,				,	0.1f ) \
		_decl( bool,			mul_with_text_color,	,	false ) \
			
#	include "Base/MetaData/MetaDataObject.h"
	

#	ifdef ENGINE_META_DATA

	namespace MetaData
	{
		template <>
		inline void MetaDataUtils::Copy<> (UIFont &left, UIFontCfg &right, const EngineSubSystemsRef ess)
		{
			ProgramPtr		prog;
			MetaDataUtils::Copy( prog, right.program, ess );
			/*
			BitmapFontPtr	font;
			BitmapFont::BitmapFontLoadParams	load_params;
			load_params.height  = 64;
			load_params.mipmaps = true;

			if ( not right.font.Empty() ) {
				CHECK_ERR( ess->GetResourceManager()->Load( EResource::BITMAP_FONT, right.font, font, load_params ), );
			}
			/*/
			VectorFontPtr	font;
			
			if ( not right.font.Empty() ) {
				CHECK_ERR( ess->GetResourceManager()->Load( EResource::VECTOR_FONT, right.font, font ), void() );
			}
			//*/
			ColorStyle	cs;
			MetaDataUtils::Copy( cs, right.colors, ess );

			if ( font.IsNotNull() ) {
				left.SetFont( font );
			}
			left.SetProgram( prog );
			left.SetSpacing( right.spacing );
			left.SetColorStyle( cs );
			left.SetMulWithTextColor( right.mul_with_text_color );
			left.SetDirection( right.text_direction == 0 ? ETextDirection::DEFAULT : (ETextDirection::type) right.text_direction );
		}
	

		template <>
		inline void MetaDataUtils::Copy<> (UITexture &left, string &right, const EngineSubSystemsRef ess)
		{
			if ( right.Empty() )
				return;

			CHECK_ERR( ess->GetUserInterface()->GetTextureManager()->Load( left, right ), void() );
		}

	}	// MetaData

#	endif


	
	//
	// UI Image Frame Indices
	//
#	define META_OBJECT			ImageStyleCfg
#	define META_OBJECT_NAME		TOSTRING( ImageStyle )
#	define META_NAME			MetaImageStyle
#	define META_BASECLASS		UIImage::FrameIndices

#	define META_FIELDS( _decl ) \
		_decl( uint8,		idle,				Idle(),				0 ) \
		_decl( uint8,		disabled,			Disabled(),			0 ) \
		_decl( uint8,		idle_pressed,		IdlePressed(),		0 ) \
		_decl( uint8,		checked,			Checked(),			0 ) \
		_decl( uint8,		checked_pressed,	CheckedPressed(),	0 )
			
#	ifdef ENGINE_META_DATA
		STATIC_ASSERT( sizeof(MetaData::UIImage::FrameIndices::index_t) == sizeof(MetaData::uint8), "incorrect type" );
#	endif
#	include "Base/MetaData/MetaDataObject.h"


	
	//
	// UI Image
	//
#	define META_OBJECT			UIImageCfg
#	define META_OBJECT_NAME		TOSTRING( Image )
#	define META_NAME			MetaImage
#	define META_BASECLASS		UIImage

#	define META_FIELDS( _decl ) \
		_decl( string,			texture,		_texture,		) \
		_decl( UIMaterialCfg,	material,		_material,		) \
		_decl( irect,			fixedBorder,	_fixedBorder,	) \
		_decl( ColorStyleCfg,	colors,			_colors,		) \
		_decl( ImageStyleCfg,	frames,			_frameIndices,	) \
		_decl( uvec2,			numFrames,		_numFrames,		) \
		_decl( uvec2,			borderSize,		_borderSize,	) \
		_decl( bool,			proportional,	_proportional,	false )
			
#	include "Base/MetaData/MetaDataObject.h"


	

	namespace MetaData
	{

#	ifdef EXTERNAL_META_DATA
		
		//
		// Locale String
		//
		struct LocaleStringCfg
		{
			string	str;
		};

		
		inline UX_DECLARE_META_TYPEDEF( LocaleStringCfg, string );
		
		template <>
		inline bool MetaDataUtils::Save<> (const WFilePtr &file, const LocaleStringCfg &value)
		{
			FILE_RW_BEGIN();

			ASSERT( value.str.Length() == sizeof(uint) );
			uint	id = *(uint const *) value.str.ptr();

			FILE_RW_CHECK( file->Write( id ) );
			
			FILE_RW_RETURN();
		}

				
		//
		// Extended Locale String
		//
		struct ExtLocaleStringCfg
		{
			string	str;
		};

		inline UX_DECLARE_META_TYPEDEF( ExtLocaleStringCfg, string );
		
		template <>
		inline bool MetaDataUtils::Save<> (const WFilePtr &file, const ExtLocaleStringCfg &value)
		{
			FILE_RW_BEGIN();

			ASSERT( value.str.Length() == sizeof(uint) );
			uint	id = *(uint const *) value.str.ptr();

			FILE_RW_CHECK( file->Write( id ) );
			
			FILE_RW_RETURN();
		}

#	endif	// EXTERNAL_META_DATA
			

#	ifdef ENGINE_META_DATA
		
		//
		// Locale String
		//
		struct LocaleStringCfg
		{
			uint	id;
			///
			LocaleStringCfg () : id(0) {}
		};


		template <>
		inline bool MetaDataUtils::Load<> (const RFilePtr &file, LocaleStringCfg &value)
		{
			return MetaDataUtils::Load( file, value.id );
		}
		
		template <>
		inline bool MetaDataUtils::Save<> (const WFilePtr &file, const LocaleStringCfg &value)
		{
			return MetaDataUtils::Save( file, value.id );
		}

		template <>
		inline void MetaDataUtils::Copy<> (string &left, LocaleStringCfg &right, const EngineSubSystemsRef ess)
		{
			CHECK_ERR( ess->GetUserInterface()->GetLocaleManager()->GetString( right.id, left ), void() );
		}

		
		
		//
		// Extended Locale String
		//
		struct ExtLocaleStringCfg
		{
			uint	id;
			///
			ExtLocaleStringCfg () : id(0) {}
		};

		template <>
		inline bool MetaDataUtils::Load<> (const RFilePtr &file, ExtLocaleStringCfg &value)
		{
			return MetaDataUtils::Load( file, value.id );
		}
		
		template <>
		inline bool MetaDataUtils::Save<> (const WFilePtr &file, const ExtLocaleStringCfg &value)
		{
			return MetaDataUtils::Save( file, value.id );
		}

		template <>
		inline void MetaDataUtils::Copy<> (ext_string &left, ExtLocaleStringCfg &right, const EngineSubSystemsRef ess)
		{
			CHECK_ERR( ess->GetUserInterface()->GetLocaleManager()->GetString( right.id, left ), void() );
		}

		template <>
		inline void MetaDataUtils::Copy<> (string &left, ExtLocaleStringCfg &right, const EngineSubSystemsRef ess)
		{
			CHECK_ERR( ess->GetUserInterface()->GetLocaleManager()->GetString( right.id, left ), void() );
		}

#	endif	// ENGINE_META_DATA

	}	// MetaData
	
	

	//
	// UI Locale Resource
	//
#	define META_OBJECT			UILocaleCfg
#	define META_OBJECT_NAME		TOSTRING( UILocale )
#	define META_NAME			MetaUILocale
#	define META_BASECLASS		UILocaleResource

#	define META_FIELDS( _decl ) \
		_decl( array<ExtStringCfg>,			strings,			_strings,	)
			
#	include "Base/MetaData/MetaDataObject.h"
	
	

	//
	// UI Locale Language
	//
#	define META_OBJECT			UILocaleLanguageCfg
#	define META_OBJECT_NAME		TOSTRING( UILanguage )
#	define META_NAME			MetaUILocaleLanguage
#	define META_BASECLASS		UILocaleSettingsResource::LangInfo

#	define META_FIELDS( _decl ) \
		_decl( array< uvec3 >,				charIntervals,		charIntervals,		) \
		_decl( string,						name,				name,				) \
		_decl( string,						iso3Name,			iso3Name,			)
			
#	include "Base/MetaData/MetaDataObject.h"
	

#	ifdef ENGINE_META_DATA
	namespace MetaData
	{
		template <>
		inline void MetaDataUtils::Copy (UILocaleSettingsResource::lang_array_t &left,
										 array<UILocaleLanguageCfg> &right,
										 const EngineSubSystemsRef ess)
		{
			left.Resize( right.Count(), false );
			
			FOR( i, left ) {
				Copy( left[i], right[i], ess );
			}
		}
	}
#	endif



	//
	// UI Locale Settings Resource
	//
#	define META_OBJECT			UILocaleSettingsCfg
#	define META_OBJECT_NAME		TOSTRING( UILocalization )
#	define META_BASECLASS		UILocaleSettingsResource

#	define META_FIELDS( _decl ) \
		_decl( array<UILocaleLanguageCfg>,	languages,		_languages,		) \
		_decl( ARGS( map<uint,string> ),	localePacks,	_localeFiles,	) \
		_decl( int,							defaultLocale,	_defaultLocale,	)
			
#	include "Base/MetaData/MetaDataObject.h"

	
	namespace MetaData
	{
		typedef string	UIActionCfg;
	}
